package com.zjpavt.client.page.abstractpage;

import com.zjpavt.client.enums.KeyCodeEnum;
import com.zjpavt.client.page.PageManager;
import com.zjpavt.client.page.intefacepage.BasePage;
import io.netty.util.concurrent.DefaultThreadFactory;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 屏幕显示页面的基类
 *
 * @author cjp
 */
@Slf4j
public abstract class AbstractBasePage implements BasePage {
    /**
     * 用于自动刷新的定时任务器
     */
//	private ScheduledExecutorService autoRefreshTimer = null;
    protected OnPageChangedListener mOnPageChangedListener = null;
    /**
     * 刷新周期
     */
    private long mRefreshPeriod = 0;
    /**
     * 当前页码
     */
    protected int mPageNum = 0;
    /**
     * 页码锁
     */
    private static final ReentrantLock pageLock = new ReentrantLock();

//	public AbstractBasePage(int pageNum) {
//		this.mPageNum = pageNum;
//	}

    /**
     * 允许0作为输入参数 效果同不初始化刷新频率
     * @param pageNum
     * @param mRefreshPeriod
     */
    public AbstractBasePage(int pageNum, long mRefreshPeriod) {
        if (mRefreshPeriod >= 0) {
            this.mRefreshPeriod = mRefreshPeriod;
            this.mPageNum = pageNum;
        } else {
            log.error("REFRESH_PERIOD can't be "+ mRefreshPeriod);
            throw new IllegalArgumentException("REFRESH_PERIOD can't be "+ mRefreshPeriod);
        }
    }

    /**
     * 是否显示 用于维护页面的显示及刷新频率
     * @param isVisible
     */
    @Override
    public void onVisibleChanged(boolean isVisible) {
        if (isVisible) {
            startAutoRefreshing();
        }
    }

    /**
     * 开始自动刷新
     */
    @Override
    public void startAutoRefreshing() {
        refreshPage();
    }

    /**
     * 获取页码
     * @return
     */
    @Override
    public int getPageNum() {
        return mPageNum;
    }


    /**
     * 开始计时器
     */
    private void startTimer() {
        /*if (REFRESH_PERIOD != 0) {
        	if (autoRefreshTimer != null) {
        		autoRefreshTimer.shutdown();
        		autoRefreshTimer = null;
        	}
        	autoRefreshTimer = new ScheduledThreadPoolExecutor(1,new DefaultThreadFactory("PageManager"));
        	autoRefreshTimer.scheduleAtFixedRate(getRefreshTask(), REFRESH_PERIOD, REFRESH_PERIOD, TimeUnit.MILLISECONDS);
        }*/
    }

    /**
     * 取消计时器
     */
    private synchronized void cancelTimer() {
        /*if (autoRefreshTimer != null) {
        	autoRefreshTimer.shutdownNow();
        	if (autoRefreshTimer.isShutdown()) {
        		log.info("STOP REFRESH SUCCESS");
        	} else {
        		cancelTimerAgain();
        		log.info("STOP REFRESH FAIL! STOP AGAIN");
        	}
        	autoRefreshTimer = null;
        }*/
    }

    private void cancelTimerAgain() {
//		if (autoRefreshTimer != null) {
//			autoRefreshTimer.shutdownNow();
//			autoRefreshTimer = null;
//		}
    }

    protected Runnable getRefreshTask() {
        return () -> {
            if (this.getPageNum() != PageManager.getInstance().getCurrPageNum() + 1) {
                //cancelTimer(); 如果不是本页 则不刷新
                log.warn("page num is :" + this.getPageNum()
                         + " currPageNum is :" + PageManager.getInstance().getCurrPageNum()
                         + " shouldn't be refreshing");
            } else {
                refreshPage();
            }
        };
    }

    protected void cancelAutoRefreshing() {
        log.trace("Page" + getPageNum() + ":cancel auto refreshing");
        if (mRefreshPeriod != 0) {
            cancelTimer();
        }
    }

    /**
     * 根据当前状态生成页面并输出到屏幕
     */
    @Override
    public abstract void refreshPage();

    /**
     * 按键监听,包括上下页翻页的处理，需要时重写
     */
    @Override
    public void onKeyPressed(KeyCodeEnum keyCodeEnum) {
        pageLock.lock();
        try {
            switch (keyCodeEnum) {
            case KEY_DOWN: {
                onKeyDown();
                break;
            }
            case KEY_UP: {
                onKeyUp();
                break;
            }
            case KEY_ENT: {
                onKeyEnt();
                break;
            }
            case KEY_SET: {
                onKeySet();
                break;
            }
            default:
                break;
            }
        }
        finally {
            pageLock.unlock();
        }
    }

    @Override
    public void onKeyDown() {
//		log.trace("Page" + getPageNum() + ":keyDown pressed");
        toNextPage();
    }

    @Override
    public void onKeyUp() {
//		log.trace("Page" + getPageNum() + ":keyUp pressed");
        toPrePage();
    }

    @Override
    public void onKeySet() {
//		log.trace("Page" + getPageNum() + ":keySet pressed");
    }

    @Override
    public void onKeyEnt() {
//		log.trace("Page" + getPageNum() + ":keyEnt pressed");
    }

    private void toPrePage() {
        cancelAutoRefreshing();
        if (mOnPageChangedListener != null) {
            mOnPageChangedListener.onPageUp();
        }
    }

    private void toNextPage() {
        cancelAutoRefreshing();
        if (mOnPageChangedListener != null) {
            mOnPageChangedListener.onPageDown();
        }
    }

    public void setOnPageChangedListener(OnPageChangedListener mOnPageChangedListener) {
        this.mOnPageChangedListener = mOnPageChangedListener;
    }

    @Override
    public abstract void close();

    public interface OnPageChangedListener {
        void onPageUp();

        void onPageDown();
    }

}
